﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System.Windows.Forms;

using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;

namespace imvs
{
    public static class EntityUtils
    {
        // 获取实体类型
        public static string GetEntityType(ObjectId id, Transaction tr = null)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            bool needCommit = false;
            if (tr == null)
            {
                tr = db.TransactionManager.StartTransaction();
                needCommit = true;
            }
            Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
            string entType = ent.GetType().Name.ToUpper();
            if (needCommit) { tr.Commit(); tr.Dispose(); }
            return entType;
        }



        // 创建圆
        public static ObjectId CreateCircle(Point3d center, double radius, string layer, Transaction tr = null)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            bool needCommit = false;
            if (tr == null)
            {
                tr = db.TransactionManager.StartTransaction();
                needCommit = true;
            }

            Circle circle = new Circle(center, Vector3d.ZAxis, radius);
            circle.Layer = layer;
            circle.ColorIndex = 1;

            BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

            ObjectId id = modelSpace.AppendEntity(circle);
            tr.AddNewlyCreatedDBObject(circle, true);

            // 事务提交前刷新图元
            UpdateScreenEx(tr, circle);

            if (needCommit) { tr.Commit(); tr.Dispose(); }
            return id;
        }

        public static void DeleteEntity(ObjectId objId, Transaction tr = null)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            bool needCommit = false;
            if (tr == null)
            {
                tr = db.TransactionManager.StartTransaction();
                needCommit = true;
            }

            DBObject obj = tr.GetObject(objId, OpenMode.ForWrite);
            if (obj != null && obj is Entity ent)
            {
                ent.Erase();

                // 事务提交前刷新图元
                UpdateScreenEx(tr, ent);

                if (needCommit) { tr.Commit(); tr.Dispose(); }
                //doc.Editor.Regen();
            }
        }

        public static ObjectId AppendToDb(Entity ent, bool update, Transaction tr)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;

            ObjectId objId = ObjectId.Null;
            //SymbolUtilityServices.GetBlockModelSpaceId(db)
            var o = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
            if (o != null && o is BlockTableRecord modelSpace)
            {
                //modelSpace.UpgradeOpen();
                objId = modelSpace.AppendEntity(ent);
                //modelSpace.DowngradeOpen();

                tr.AddNewlyCreatedDBObject(ent, true);

                if (update)
                {
                    // 事务提交前刷新图元
                    UpdateScreenEx(tr, ent);
                }
            }
            return objId;

        }

        // 创建直线
        public static ObjectId CreateLine(Point3d start, Point3d end, string layer = null, Transaction tr = null)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            bool needCommit = false;
            if (tr == null)
            {
                tr = db.TransactionManager.StartTransaction();
                needCommit = true;
            }

            ObjectId lineId = ObjectId.Null;
            //using (DocumentLock m_DocumentLock = doc.LockDocument())
            //{
            Line line = new Line(start, end);
            if (!string.IsNullOrEmpty(layer))
            {
                line.Layer = layer;
            }


            //SymbolUtilityServices.GetBlockModelSpaceId(db)
            var o = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
            if (o != null && o is BlockTableRecord modelSpace)
            {
                //modelSpace.UpgradeOpen();
                lineId = modelSpace.AppendEntity(line);
                //modelSpace.DowngradeOpen();

                tr.AddNewlyCreatedDBObject(line, true);

                // 事务提交前刷新图元
                UpdateScreenEx(tr, line);
            }

            //}

            if (needCommit) { tr.Commit(); tr.Dispose(); }
            return lineId;
        }

        // 修改圆的圆心和半径
        public static bool SetCircleProperties(ObjectId id, Point3d center, double radius, Transaction tr = null)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            bool needCommit = false;
            if (tr == null)
            {
                tr = db.TransactionManager.StartTransaction();
                needCommit = true;
            }

            Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
            bool ret = false;
            if (ent is Circle circle)
            {
                circle.Center = center;
                circle.Radius = radius;
                ret = true;

                // 事务提交前刷新图元
                UpdateScreenEx(tr, circle);

                if (needCommit) { tr.Commit(); tr.Dispose(); }
                //doc.Editor.Regen();
            }

            return ret;
        }

        // 修改直线的端点
        public static bool SetLinePoints(ObjectId id, Point3d start, Point3d end, Transaction tr = null)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            bool needCommit = false;
            if (tr == null)
            {
                tr = db.TransactionManager.StartTransaction();
                needCommit = true;
            }

            //using (Transaction tr = id.Database.TransactionManager.StartTransaction())
            //{
            Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
            bool ret = false;
            if (ent is Line line)
            {
                line.StartPoint = start;
                line.EndPoint = end;
                ret = true;

                // 事务提交前刷新图元
                UpdateScreenEx(tr, line);

                if (needCommit) { tr.Commit(); tr.Dispose(); }
                //doc.Editor.Regen();
            }
            return ret;
            //}
        }

        public static ObjectId GetEntityOnLayer(string entityType, string layerName)
        {
            Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            // 创建筛选条件列表
            TypedValue[] filterList = new TypedValue[]
            {
            new TypedValue((int)DxfCode.Start, entityType),  // 图元类型
            new TypedValue((int)DxfCode.LayerName, layerName)  // 图层名
            };

            SelectionFilter filter = new SelectionFilter(filterList);

            try
            {
                // 执行选择操作（"X"模式表示整个数据库搜索）
                PromptSelectionResult psr = ed.SelectAll(filter);
                if (psr.Status == PromptStatus.OK)
                {
                    var ss = psr.Value;
                    if (ss == null || ss.Count == 0)
                    {
                        return ObjectId.Null;
                    }
                    else
                    {
                        return ss[0].ObjectId;
                    }
                }
                else
                {
                    return ObjectId.Null;
                }
            }
            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ed.WriteMessage($"\n选择错误: {ex.Message}");
                return ObjectId.Null;
            }
        }

        //https://www.cnblogs.com/JJBox/p/11354224.html
        public static void UpdateScreenEx(Transaction tr, Entity ent = null, OpenMode om = OpenMode.ForWrite)
        {
            if (ent != null)
            {
                if (om == OpenMode.ForWrite)
                    ent.UpgradeOpen();
                // 图元重绘
                ent.Draw();
                // move0要提权才有效果,不然也不报错
                ent.TransformBy(Matrix3d.Displacement(new Vector3d(0, 0, 0)));
                // 图块刷新
                ent.RecordGraphicsModified(true);
                if (ent is BlockReference brf)
                {
                    // 更新动态块
                    var btr = (BlockTableRecord)tr.GetObject(brf.BlockTableRecord, OpenMode.ForWrite);
                    btr.UpdateAnonymousBlocks();
                }
                else if (ent is Dimension dim) dim.RecomputeDimensionBlock(true);
                else if (ent is Viewport vp) vp.UpdateDisplay();
            }

            // 底层差不多ed.UpdateScreen();
            AcadApplication.UpdateScreen();
            // acad2014及以上要加,立即处理队列上面的消息
            System.Windows.Forms.Application.DoEvents();
        }
    }

}
